//Copyright 2011 New York City 3D Community

//This file is part of New York City 3D.

//New York City 3D is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//New York City 3D is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with New York City 3D.  If not, see <http://www.gnu.org/licenses/>.

package nyc3d;

import com.jme3.asset.AssetManager;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Node;

/**
 *
 * @author Walkable person
 */

public class Human implements ActionListener{
    CharacterControl character;
    Vector3f defaultLocation = new Vector3f(0, 10, 29);
    Matrix3f rotation;
    Node parentNode;
    private Vector3f walkDirection = new Vector3f();
    private boolean left = false, right = false, up = false, down = false;

    public Human(Vector3f position, Camera camera, AssetManager assetManager, InputManager inputManager, PhysicsSpace pSpace, Node parentNode){
        rotation = new Matrix3f();
        rotation.fromAngleAxis(FastMath.PI /2f -.1437440552f, Vector3f.UNIT_Y);
        setupKeys(inputManager);

        character = new CharacterControl(new CapsuleCollisionShape(.75f, 5.578125f, 1), .05f);
        character.setPhysicsLocation(defaultLocation);
        //character.setPhysicsRotation(rotation);
        character.setJumpSpeed(20);
        character.setFallSpeed(30);
        character.setGravity(30); 

        //parentNode.attachChild(character);
        pSpace.add(character);  
    }

    private void setupKeys(InputManager inputManager){
        inputManager.addMapping("Walk Left",  new KeyTrigger(KeyInput.KEY_A));
        inputManager.addMapping("Walk Right", new KeyTrigger(KeyInput.KEY_D));
        inputManager.addMapping("Walk Forward",    new KeyTrigger(KeyInput.KEY_W));
        inputManager.addMapping("Walk Backward",  new KeyTrigger(KeyInput.KEY_S));
        inputManager.addMapping("Jump Character",  new KeyTrigger(KeyInput.KEY_SPACE));
        inputManager.addMapping("Reset Character",  new KeyTrigger(KeyInput.KEY_RETURN));
        inputManager.addListener(this, "Walk Left");
        inputManager.addListener(this, "Walk Right");
        inputManager.addListener(this, "Walk Forward");
        inputManager.addListener(this, "Walk Backward");
        inputManager.addListener(this, "Jump Character");
        inputManager.addListener(this, "Reset Character");
    }

    public void update(Camera cam){
        Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);
        Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
        walkDirection.set(0, 0, 0);
        if (left)  { walkDirection.addLocal(camLeft); }
        if (right) { walkDirection.addLocal(camLeft.negate()); }
        if (up)    { walkDirection.addLocal(camDir); }
        if (down)  { walkDirection.addLocal(camDir.negate()); }
        character.setWalkDirection(walkDirection);
        cam.setLocation(character.getPhysicsLocation().add(0, 3, 0));
    }

    public void onAction(String binding, boolean value, float tpf) {
        if (binding.equals("Walk Left")) {
          if (value) { left = true; }  else { left = false; }
        } else if (binding.equals("Walk Right")) {
          if (value) { right = true; } else { right = false; }
        } else if (binding.equals("Walk Forward")) {
          if (value) { up = true; }    else { up = false; }
        } else if (binding.equals("Walk Backward")) {
          if (value) { down = true; }  else { down = false; }
        } else if (binding.equals("Jump Character")) {
          character.jump();
        } else if (binding.equals("Reset Character")){
            character.setPhysicsLocation(defaultLocation);
            //character.setPhysicsRotation(rotation);
        }
    }

    public Node getParentNode() {
        return parentNode;
    }

    public void setParentNode(Node parentNode) {
        this.parentNode = parentNode;
    }
}